<?php

declare(strict_types=1);

namespace App\Order\Service;

use App\Common\Constants\ErrorCode;
use App\Common\Service\BaseService;
use App\Common\Constants\Stakeholder;
use App\Order\Model\OrderGoodsModel;
use App\Order\Model\OrderModel;
use App\Order\Model\OrderRefundModel;
use App\Order\Model\TemplateWidgetModel;
use App\Order\Model\WidgetModel;
use App\Order\Repository\RepositoryFactory;
use App\Resource\Model\SystemModel;
use App\Resource\Service\ShopService;
use App\Resource\Service\TeamLeaderService;
use App\Third\Service\Log\KzRefundLogService;
use App\Third\Service\Log\WxRefundLogService;
use Hyperf\AsyncQueue\Driver\DriverFactory;
use Hyperf\Contract\LengthAwarePaginatorInterface;
use Hyperf\Database\Model\Builder;
use Hyperf\Database\Model\Model;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Logger\LoggerFactory;

class OrderService extends BaseService
{
    /**
     * 送货方式：(1配送订单,2为自提订单)
     */
    const ORDER_DEAL_TYPE_1 = 1;
    const ORDER_DEAL_TYPE_2 = 2;
    /**
     * 订单类型(0 普通订单   2、普通自提订单  6 团购自提订单 7接龙订单 8次日达精选 9 次日达秒杀订单)
     */
    const ORDER_TYPE_0 = 0;
    const ORDER_TYPE_2 = 2;
    const ORDER_TYPE_6 = 6;
    const ORDER_TYPE_7 = 7;
    const ORDER_TYPE_8 = 8;
    const ORDER_TYPE_9 = 9;
    const ORDER_TYPE_10 = 10;
    /**
     * 订单类别区分 0及时达、1次日达订单
     */
    const ORDER_SOURCE_0 = 0;
    const ORDER_SOURCE_1 = 1;


    /**
     * 购物车商品类型 1及时达、2次日达
     */
    const CART_SOURCE_1 = 1;
    const CART_SOURCE_2 = 2;

    /**
     * 订单支付状态： 0：未支付  1：已支付
     */
    const ORDER_IS_PAY_0 = 0;
    const ORDER_IS_PAY_1 = 1;

    /**
     * 订单状态(0,已取消，1.待付款,2.待发货,3.待取货,4已收货(已核销),5.已退款,6已拒绝,7待处理,8配送中)
     */
    const ORDER_STATUS_0 = 0;
    const ORDER_STATUS_1 = 1;
    const ORDER_STATUS_2 = 2;
    const ORDER_STATUS_3 = 3;
    const ORDER_STATUS_4 = 4;
    const ORDER_STATUS_5 = 5;
    const ORDER_STATUS_6 = 6;
    const ORDER_STATUS_7 = 7;

    /**
     * @Inject()
     * @var KzRefundLogService
     */
    private $kzRefundLogService;

    /**
     * @Inject()
     * @var WxRefundLogService
     */
    private $wxRefundLogService;

    /**
     * @Inject()
     * @var OrderGoodsService
     */
    private $orderGoodsService;


    /**
     * @Inject()
     * @var BaseService
     */
    private $baseService;

    /**
     * @Inject()
     * @var ShopService
     */
    private $shopService;

    private $log;
    protected $driver;
    protected $orderRepository;
    public function __construct(LoggerFactory $loggerFactory,DriverFactory $driverFactory,RepositoryFactory $repoFactory)
    {
        parent::__construct();
        $this->log = $loggerFactory->get('order.log', 'default');
        $this->driver = $driverFactory->get('order');
        $this->orderRepository = $repoFactory->getRepository("order");
    }

    /**
     * 订单详情基本信息
     * @param array $where
     * @param array|string[] $field
     * @param string|null $refund_no
     * @return array|Builder|Model|object
     */
    public function find(array $where = [], array $field = ['*'], string $refund_no = null)
    {
        $orderInfo = $this->orderRepository->findFirst($where, $field);
        if (!$orderInfo)
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '订单不存在'];
        $order = [
            'order_no' => $orderInfo->order_no, //订单编号
            'is_freed' => $orderInfo->is_freed, //订单编号
            'refund_no' => $refund_no, //退款单号
            'nickname' => $orderInfo->member->nickname, //用户昵称
            'order_phone' => $orderInfo->member->phone, //手机号码
            'kz_cus_code' => $orderInfo->member->kz_cus_code, //客至编号
            'deal_type' => $orderInfo->deal_type, //配送方式 1配送订单,2为自提订单
            'status' => $orderInfo->status, //订单状态
            'order_type' => $orderInfo->order_type, //订单类型
            'shop_name' => $orderInfo->shop->shop_name, //下单店铺
            'shop_phone' => $orderInfo->shop->shop_tel, //店铺电话
            'shop_time' => $orderInfo->shop->shop_desc, //营业时间
            'shop_address' => $orderInfo->shop->address, //营业时间
            'create_at' => $orderInfo->create_at, //下单时间
            'pay_at' => $orderInfo->pay_at, //支付时间
            'is_whole' => $orderInfo->is_whole, //0：整单  1：部分
            'appointment_time' => $orderInfo->appointment_time, //配送时间(自提时间)
            'apply_refund_at' => $orderInfo->refund->create_at ?? '', //申请退款时间
            'complete_date' => $orderInfo->complete_date, //订单完成时间
            'refund_at' => $orderInfo->refund_at ?? '', //退款完成时间
            'order_source' => $orderInfo->order_source ?? 0, //0、及时达 1 次日达
            'order_commission' => $orderInfo->order_commission ?? '0.00' //退款完成时间
        ];
        if ($orderInfo->deal_type == Stakeholder::ORDER_SELF_PICK) {
            // 自提订单
            $order['receive_name'] = $orderInfo->member->nickname;
            $order['receive_phone'] = $orderInfo->member->phone;
            $order['receive_address'] = $orderInfo->shop->address;
        } else {
            $order['receive_name'] = $orderInfo->address->username;
            $order['receive_phone'] = $orderInfo->address->phone;
            $order['receive_address'] = $orderInfo->address->area . ' ' . $orderInfo->address->address;
        }
        $order['free_status'] =1;
        if($orderInfo->order_type==self::ORDER_TYPE_10){
            $order['free_status'] = $this->getFreeStatus($orderInfo);
        }
        return ['code' => 1, 'data' => $order, 'msg' => '获取订单基本信息成功'];
    }

    /**
     * 订单详情商品信息
     * @param array $where
     * @param array|string[] $field
     * @return array
     */
    public function findGoods(array $where = [], array $field = ['*'])
    {
        $orderInfo = $this->orderRepository->findFirst($where, ['order_source','goods_price','order_commission']);
        if (!$orderInfo)
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '订单不存在'];
        $list = $this->findGoodsDo($where, $field);
        foreach ($list as $k => $v) {
            $list[$k]['subtotal'] = $v['dis_price']; // 小计
            $list[$k]['refund_subtotal'] = $v['refund_price']; // 退款小计
            $list[$k]['refund_num'] = $v['number'] - $v['refund_number'] - $v['shop_refund_number']; // 退款数量
            $list[$k]['order_source'] = $orderInfo->order_source;
//            if ($v['dis_price'] == 0){
//                $list[$k]['subtotal'] = bcmul((string) $v['selling_price'], (string) $v['number'], 2);
//            }
        }
        return [
            'code' => 1,
            'data' => [
                'total_amount' => $orderInfo->goods_price,
                'total_commission' => $orderInfo->order_commission,
                'list' => $list
            ],
            'msg' => '获取订单商品信息成功'
        ];
    }

    /**
     * 订单商品列表
     * @param array $where
     * @param array|string[] $field
     * @return array
     */
    public function findGoodsDo(array $where = [], array $field = ['*'])
    {
        return $this->orderGoodsService->getOrderGoodsList($where, $field);
    }

    /**
     * 订单详情费用信息
     * @param array $where
     * @param array|string[] $field
     * @return array
     */
    public function findCost(array $where = [], array $field = ['*'])
    {
        $cost = $this->orderRepository->findFirst($where, $field);
        if (!$cost)
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '订单不存在'];
        $cost->sum_amount = $cost->total_price; // 应付款金额
        $cost->activity = 0; // 优惠活动
        $cost->discount = 0; // 折扣金额
        return ['code' => 1, 'data' => $cost, 'msg' => '获取订单费用信息成功'];
    }

    /**
     * 查询订单列表 by where
     * @param array $where
     * @param array|string[] $field
     * @return LengthAwarePaginatorInterface
     */
    public function get(array $where = [], array $field = ['*'])
    {
        $where = $this->conditionWhere($where);
        $orderGoods = OrderGoodsModel::query()
            ->selectRaw('GROUP_CONCAT(goods_title) as order_goods_name,order_no')
//            ->when($where['order_no'] ?? 0, function ($query, $order_no) {
//                return $query->where('order_no', $order_no);
//            })
            ->when($where['mid'] ?? 0, function ($query, $mid) {
                return $query->where('mid', $mid);
            })
            ->when($where['shop_id'] ?? 0, function ($query, $shop_id) {
                return $query->where('shop_id', $shop_id);
            })
            ->when($where['create_at'] ?? 0, function ($query, $create_at) {
                return $query->whereBetween('create_at', $create_at);
            })->groupBy(['order_no']);

        $order = OrderModel::query()
            ->from('store_order as order')
            ->leftJoin('store_shop as shop', 'order.shop_id', '=', 'shop.shop_id')
            ->leftJoin('store_member as member', 'order.mid', '=', 'member.mid')
            ->leftJoin('store_member_address as addr', 'order.address_id', '=', 'addr.id')
            ->select($field)
            ->joinSub($orderGoods, 'goods', function ($join) {
                $join->on('order.order_no', '=', 'goods.order_no');
            })
            ->when($where['order_no'] ?? 0, function ($query)use($where) {
                if($where['order_type']==self::ORDER_TYPE_10){
                    $query->whereRaw("CONCAT(order.order_no, order.free_parent_order_no) like  '%{$where['order_no']}%'");
                }else{
                    return $query->where('order.order_no', $where['order_no']);
                }
            })
            ->when($where['create_at'] ?? 0, function ($query, $create_at) {
                return $query->whereBetween('order.create_at', $create_at);
            })
            ->when($where['pay_at'] ?? 0, function ($query, $pay_at) {
                return $query->whereBetween('order.pay_at', $pay_at);
            })
            ->when($where['refund_at'] ?? 0, function ($query, $refund_at) {
                return $query->whereBetween('order.refund_at', $refund_at);
            })
            ->when($where['appointment_date'] ?? 0, function ($query, $appointment_date) {
                return $query->whereBetween('order.appointment_date', $appointment_date);
            })
            ->when($where['complete_date'] ?? 0, function ($query, $complete_date) {
                return $query->whereBetween('order.complete_date', $complete_date);
            })
            ->when($where['phone'] ?? 0, function ($query, $phone) {
                return $query->where('order.order_phone', $phone);
            })
            ->when($where['shop_id'] ?? 0, function ($query, $shop_id) {
                return $query->where('order.shop_id', $shop_id);
            })
            ->when($where['pay_type'] ?? 0, function ($query, $pay_type) {
                return $query->where('order.pay_type', $pay_type);
            })
            ->when(is_numeric($where['order_type']), function ($query) use ($where) {
                return $query->where('order.order_type', $where['order_type']);
            })
            ->when(is_numeric($where['order_status']), function ($query) use ($where) {
                return $query->where('order.status', $where['order_status']);
            })
            ->when($where['mid'] ?? 0, function ($query, $mid) {
                return $query->where('order.mid', $mid);
            })
            ->when($where['activityId'] ?? 0, function ($query, $activityId) {
                return $query->where('order.activity_id', $activityId);
            })
            ->when($where['goods_name'] ?? 0, function ($query, $goods_name) {
                return $query->whereRaw('INSTR(order_goods_name, ?) > 0', [$goods_name]);
            })
            ->when(is_numeric($where['order_source']), function ($query) use ($where) {
                return $query->where('order.order_source', $where['order_source']);
            })
            ->when($where['free_status']??0, function ($query) use ($where) {
                $freePayWhere =[];
                $freeWhereIn =[];
                //1待支付2分享中3彻底失败4免单成功
                switch ($where['free_status']){
                    case 1:
                        $freePayWhere = ['order.status'=>1];
                        break;
                    case 2:
                        $freePayWhere = ['order.is_pay'=>1];
                        $freeWhereIn = [0];
                        break;
                    case 3:
                        $freeWhereIn = [1,3];
                        break;
                    case 4:
                        $freeWhereIn = [2,4];
                        break;
                    default:
                        break;
                }
                return $freeWhereIn?$query->where($freePayWhere)->whereIN('is_freed',$freeWhereIn):$query->where($freePayWhere);
            })
            ->latest('create_at')
            ->when($where['perpage'] ?? 0, function ($query, $perPage) {
                return $query->paginate((int)$perPage);
            }, function ($query) {
                return $query->get();
            });

        return $order;
    }

    /**
     * 获取免单好友明细
     * @param array $where
     * @param array|string[] $field
     * @return array
     */
    public function getOrderSub(array $where,array $field=['*'])
    {
        $order = $this->orderRepository->getOrderSubDetail($where,$field);
        return $order;
    }

    /**
     * 导出拼团配货单
     * @param array $where
     * @param array $field
     * @param int $flag
     * @return array
     */
    public function distribution(array $where, array $field, int $flag)
    {
        $where = $this->conditionWhere($where);
        $shopNameArr = $this->container->get(ShopService::class)->getShopNameData();
        $order = OrderModel::query()
            ->from('store_order as order')
            ->leftJoin('store_order_goods as og', 'order.order_no', '=', 'og.order_no')
            ->selectRaw(implode(',', $field))
            ->when($where['create_at'] ?? 0, function ($query, $create_at) {
                return $query->whereBetween('order.create_at', $create_at);
            })
            ->when($where['pay_at'] ?? 0, function ($query, $pay_at) {
                return $query->whereBetween('order.pay_at', $pay_at);
            })
            ->when($where['appointment_date'] ?? 0, function ($query, $appointment_date) {
                return $query->whereBetween('order.appointment_date', $appointment_date);
            })
            ->when($where['complete_date'] ?? 0, function ($query, $complete_date) {
                return $query->whereBetween('order.complete_date', $complete_date);
            })
            ->when($where['pay_type'] ?? 0, function ($query, $pay_type) {
                return $query->where('order.pay_type', $pay_type);
            })
            ->when(is_numeric($where['order_type']), function ($query) use ($where) {
                return $query->where('order.order_type', $where['order_type']);
            })
            ->when(is_numeric($where['order_source']), function ($query) use ($where) {
                return $query->where('order.order_source', $where['order_source']);
            })
            ->whereNotIn('order.status', [Stakeholder::ORDER_CANCEL, Stakeholder::ORDER_REFUNDED])
            ->groupBy(['shop_id', 'goods_id'])
            ->when($param['perpage'] ?? 0, function ($query, $perPage) {
                return $query->paginate((int)$perPage);
            }, function ($query) {
                return $query->get();
            });
        if (isset($where['perpage']) && !empty($where['perpage'])) {
            $items = $order->items();
        } else {
            $items = $order->toArray();
        }
        if (!empty($items)) {
            $list = [];
            $goodsInfo = array_unique(array_column($items, 'goods_title', 'goods_id'));
            $diff = array_fill_keys(array_keys($goodsInfo), 0);
            ksort($goodsInfo);
            $goodsInfo = ['header' => '门店'] + $goodsInfo;
            foreach ($order as $k => $v) {
                foreach ($shopNameArr as $kk => $vv) {
                    $list[$kk]['shop_name'] = $vv;
                    if ($v['shop_id'] == $kk) {
                        $list[$v['shop_id']][$v['goods_id']] = (int)$v['num'];
                    }
                }
            }
            foreach ($list as $k => $v) {
                $map = $v + $diff;
                ksort($map);
                $list[$k] = $map;
            }
            // 合计
            foreach ($items as $k => $v) {
                $diff[$v['goods_id']] += $v['num'];
            }
            array_unshift($list, $goodsInfo);
            $endMap = ['shop_name' => '合计'] + $diff;
            ksort($endMap);
            array_push($list, $endMap);
            return $list;
        }
        return $order;
    }

    /**
     * 导出疏东坡报货模板
     * @param array $where
     * @param array $field
     * @return \Hyperf\Database\Concerns\BuildsQueries|Builder|\Hyperf\Database\Query\Builder|mixed
     */
    public function shuDongPoTemp(array $where, array $field)
    {
        $where = $this->conditionWhere($where);
        $order = OrderModel::query()
            ->from('store_order as order')
            ->leftJoin('store_shop as shop', 'order.shop_id', '=', 'shop.shop_id')
            ->leftJoin('store_order_goods as og', 'order.order_no', '=', 'og.order_no')
            ->leftJoin('store_goods as g', 'og.goods_id', '=', 'g.id')
            ->selectRaw(implode(',', $field))
            ->when($where['create_at'] ?? 0, function ($query, $create_at) {
                return $query->whereBetween('order.create_at', $create_at);
            })
            ->when($where['pay_at'] ?? 0, function ($query, $pay_at) {
                return $query->whereBetween('order.pay_at', $pay_at);
            })
            ->when($where['appointment_date'] ?? 0, function ($query, $appointment_date) {
                return $query->whereBetween('order.appointment_date', $appointment_date);
            })
            ->when($where['complete_date'] ?? 0, function ($query, $complete_date) {
                return $query->whereBetween('order.complete_date', $complete_date);
            })
            ->when($where['pay_type'] ?? 0, function ($query, $pay_type) {
                return $query->where('order.pay_type', $pay_type);
            })
            ->when(is_numeric($where['order_type']), function ($query) use ($where) {
                return $query->where('order.order_type', $where['order_type']);
            })
            ->when(is_numeric($where['order_source']), function ($query) use ($where) {
                return $query->where('order.order_source', $where['order_source']);
            })
            ->when($where['shop_id'] ?? 0, function ($query, $shop_id) {
                return $query->where('order.shop_id', $shop_id);
            })
            ->when($where['goods_name'] ?? 0, function ($query, $goods_name) {
                return $query->whereRaw('INSTR(og.goods_title, ?) > 0', [$goods_name]);
            })
            ->whereNotIn('order.status', [Stakeholder::ORDER_CANCEL,Stakeholder::ORDER_RECEIVED, Stakeholder::ORDER_REFUNDED])
            ->groupBy(['shop_id', 'goods_id'])
            ->when($param['perpage'] ?? 0, function ($query, $perPage) {
                return $query->paginate((int)$perPage);
            }, function ($query) {
                return $query->get();
            });
        return $order;
    }

    /**
     * 组合订单列表数据
     * @param array $where
     * @param array|string[] $field
     * @return LengthAwarePaginatorInterface
     */
    public function list(array $where = [], array $field = ['*'])
    {
        $order = $this->get($where, $field);
        if (isset($where['perpage']) && !empty($where['perpage'])) {
            $items = $order->items();
        } else {
            $items = $order->toArray();
        }

        $orderNoArr = array_unique(array_column($items, 'order_no'));
//        $orderGoodsNameArr = $this->orderGoodsService->orderGoodsName($orderNoArr);
//        $orderGoodsName = array_column($orderGoodsNameArr, 'goods_title', 'order_no');

        $refundInfo = $this->refundInfo($orderNoArr);

        $refund = [];
        foreach ($order as $k => $v) {
            $order[$k]['phone'] = $v['order_phone'];
            $order[$k]['refund_type'] = is_null($v['refund_at']) ? '':'部分退';
            $order[$k]['refund_at'] = $v['refund_at'] ?? '--';
//            $order[$k]['order_goods_name'] = $orderGoodsName[$v['order_no']];
            if ($v['address_id'] == 0) {
                // 自提单
                $order[$k]['receive_username'] = $v['nickname']; //收货人姓名
                $order[$k]['receive_phone'] = $v['mem_phone']; //收货人手机号码
            } else {
                // 配送单
                $order[$k]['receive_username'] = $v['addr_username'];
                $order[$k]['receive_phone'] = $v['addr_phone'];
            }
            // 退款信息
            if (($v['is_pay'] == Stakeholder::ORDER_PAID)) {
                if (isset($refundInfo['wxRefund'][$v['order_no']]) || isset($refundInfo['kzRefund'][$v['order_no']])) {
                    $refund['refund_freight'] = '0.00';// 退款运费
                    if ($v['pay_type'] == Stakeholder::PAYMENT_METHOD_WECHAT) {
                        // 微信支付
                        $refund['refund_wx_money'] = $refundInfo['wxRefund'][$v['order_no']] ?? '0.00';
                        $refund['refund_total'] = $refund['refund_wx_money']; // 退款总金额
                    }
                    if ($v['pay_type'] == Stakeholder::PAYMENT_METHOD_BALANCE) {
                        // 余额支付
                        $refund['refund_balance_money'] = $refundInfo['kzRefund'][$v['order_no']] ?? '0.00';
                        $refund['refund_total'] = $refund['refund_balance_money']; // 退款总金额
                    }
                    if ($v['status'] == Stakeholder::ORDER_REFUNDED) {
                        if ($v['is_whole'] == Stakeholder::WHOLE_REFUND) {
                            $refund['refund_freight'] = bcsub((string)$v['freight_price'], (string)$v['coupon_freight_cut'], 2);// 退款运费
                            $refund['refund_total'] = $v['total_price']; // 退款总金额
                            $order[$k]['refund_type'] = '全部退';
                        }
                    }
                }

            }
            $order[$k]['free_status'] =1;
            if($v['order_type']==self::ORDER_TYPE_10){
                $order[$k]['free_status'] = $this->getFreeStatus($v);
            }
            $order[$k]['refund'] = $refund ?? [];
            unset($refund);
        }
        return $order;
    }

    /**
     *  1待支付2分享中3彻底失败成功4免单成功
     * @param array $order
     * @return int
     */
    public function getFreeStatus(object $order)
    {
           $freeStatus = 1;
            if ($order['is_freed'] == 0 && $order['is_pay']==Stakeholder::ORDER_PAID) {
                $freeStatus = 2;
            } elseif (in_array($order['is_freed'],[1,3])) {
                $freeStatus = 3;
            } elseif (in_array($order['is_freed'],[2,4])) {
                $freeStatus = 4;
            }

        return $freeStatus;
    }
    /**
     * 财务订单导出
     * @param array $where
     * @param array|string[] $field
     * @param int $flag
     * @return LengthAwarePaginatorInterface
     */
    public function export(array $where = [], array $field = ['*'], int $flag)
    {

        switch ($flag) {
            case 1:
                // 财务订单导出
                $order = $this->get($where, $field);

                if (isset($where['perpage']) && !empty($where['perpage'])) {
                    $items = $order->items();
                } else {
                    $items = $order->toArray();
                }

                $orderNoArr = array_unique(array_column($items, 'order_no'));
                $refund = $this->refundInfo($orderNoArr);

                foreach ($order as $k => $v) {
                    // 商品原金额
                    $order[$k]['original_amt'] = bcadd((string)$v['goods_price'], bcsub((string)$v['coupon_cut'], (string)$v['coupon_freight_cut'], 2), 2);
                    // 应收金额
                    $order[$k]['receivable_amt'] = bcadd($order[$k]['original_amt'], (string)$v['freight_price'], 2);
                    $order[$k]['refund_at'] = $v['refund_at'] ?? '';
                    // 微信退款金额
                    $order[$k]['refundWxMoney'] = $refund['wxRefund'][$v['order_no']] ?? '0.00';
                    // 余额退款金额
                    $order[$k]['refundKzMoney'] = $refund['kzRefund'][$v['order_no']] ?? '0.00';
                    // 实际实收金额
                    $order[$k]['true_receivable_amt'] = bcsub((string)$v['total_price'],bcadd((string)$order[$k]['refundWxMoney'], (string)$order[$k]['refundKzMoney'], 2),2);
                }
                break;
            case 2:
                // 配货单
                $order = $this->distribution($where, $field, $flag);
                break;
            case 3:
                // 疏东坡模板导出
                $res = $this->shuDongPoTemp($where, $field);
                $order = [];
                foreach ($res->toArray() as $k => $v){
                    $key = $v['shop_id'] . $v['goods_title'];
                    if(!isset($order[$key])){
                        $order[$key] = $v;
                    }else{
                        $order[$key]['num'] = bcadd((string)$order[$key]['num'], (string)$v['num'], 4);
                    }
                }
                $order = array_values($order);
                break;
            default:
        }
        return $order;
    }

    /**
     * 退款信息
     * @param array $orderNoArr
     * @return array
     */
    public function refundInfo(array $orderNoArr)
    {
        // 退款信息
        // 客至
        $kzRefundArr = $this->kzRefundLogService->refundInfo($orderNoArr);
        // 吾享
        $wxRefundArr = $this->wxRefundLogService->refundInfo($orderNoArr);

        $kzRefund = array_column($kzRefundArr, 'refund_balance_money', 'order_no');
        $wxRefund = array_column($wxRefundArr, 'refund_wx_money', 'order_no');

        return ['kzRefund' => $kzRefund, 'wxRefund' => $wxRefund];
    }

    /**
     * 次日达商品每人每天已经购买的数量
     * @param array $where
     * @param array|null $in
     * @return array
     */
    public function nextDayGoodsNumOfMid(array $where, ?array $in = null){
        $field = [
            'sum(og.number) as num',
            'og.goods_id',
        ];
        return OrderModel::query()
            ->from('store_order as order')
            ->rightJoin('store_order_goods as og', 'order.order_no', '=', 'og.order_no')
            ->selectRaw(implode(',', $field))
            ->where($where)
            ->where('order.order_source', Stakeholder::NEXT_DAY_ORDER)
            ->where('order.is_pay', Stakeholder::ORDER_PAID)
            ->whereBetween('order.pay_at', [date('Y-m-d'), date('Y-m-d 23:59:59')])
            ->when($in, function ($query, $in) {
                foreach ($in as $k => $v) {
                    $query->whereIn($v[0], $v[1]);
                }
                return $query;
            })
            ->groupBy(['goods_id'])
            ->get()->toArray();
    }

    /**
     * 条件组合
     * @param array $where
     * @return array
     */
    public function conditionWhere(array $where)
    {
        $payAt = $where['pay_at'] ?? '';
        $createAt = $where['create_at'] ?? '';
        $refundAt = $where['refund_at'] ?? '';
        $completeDate = $where['complete_date'] ?? '';
        $appointmentDate = $where['appointment_date'] ?? '';
        $where['order_source'] = $where['order_source'] ?? '';
        if (!empty($createAt) && strlen(trim($createAt)) > 23) {
            $where['create_at'] = [trim(substr($createAt, 0, 19)), trim(substr($createAt, -19))];
        }
        if (!empty($createAt) && strlen(trim($createAt)) < 24) {
            $where['create_at'] = [trim(substr($createAt, 0, 10)), trim(substr($createAt, -10))];
        }
        if (!empty($payAt) && strlen(trim($payAt)) > 23) {
            $where['pay_at'] = [trim(substr($payAt, 0, 19)), trim(substr($payAt, -19))];
        }
        if (!empty($payAt) && strlen(trim($payAt)) < 24) {
            $where['pay_at'] = [trim(substr($payAt, 0, 10)), trim(substr($payAt, -10))];
        }
        if (!empty($refundAt) && strlen(trim($refundAt)) > 23) {
            $where['refund_at'] = [trim(substr($refundAt, 0, 19)), trim(substr($refundAt, -19))];
        }
        if (!empty($refundAt) && strlen(trim($refundAt)) < 24) {
            $where['refund_at'] = [trim(substr($refundAt, 0, 10)), trim(substr($refundAt, -10))];
        }
        if (!empty($completeDate) && strlen(trim($completeDate)) > 23) {
            $where['complete_date'] = [trim(substr($completeDate, 0, 19)), trim(substr($completeDate, -19))];
        }
        if (!empty($completeDate) && strlen(trim($completeDate)) < 24) {
            $where['complete_date'] = [trim(substr($completeDate, 0, 10)), trim(substr($completeDate, -10))];
        }
        if (!empty($appointmentDate) && strlen(trim($appointmentDate)) > 23) {
            $where['appointment_date'] = [trim(substr($appointmentDate, 0, 19)), trim(substr($appointmentDate, -19))];
        }
        if (!empty($appointmentDate) && strlen(trim($appointmentDate)) < 24) {
            $where['appointment_date'] = [trim(substr($appointmentDate, 0, 10)), trim(substr($appointmentDate, -10))];
        }
        return $where;
    }

    /**
     * 根据付款时间区间获取下单手机号
     * @param array $dateArr
     * @return array
     */
    public function getOrderPhoneByDateRange(array $dateArr = [])
    {
        if (!empty($dateArr)) {
            return OrderModel::query()
                ->whereBetween('pay_at', [$dateArr['start'], $dateArr['end']])
                ->pluck('order_phone')
                ->toArray();
        }
        return [];

    }

    /**
     * 获取会员总消费
     * @param int $mid
     * @return int|mixed
     */
    public function getMemberTotalPayment(int $mid)
    {
        return OrderModel::query()->where([
            ['mid', '=', $mid],
            ['is_pay', '=', Stakeholder::ORDER_PAID],
            ['status', '!=', Stakeholder::ORDER_REFUNDED]
        ])->sum('total_price');
    }


    public function findFirst(array $where = [], array $field = ['*'])
    {
        return OrderModel::query()
            ->select($field)
            ->where($where)
            ->first();
    }

    // 优惠券是否已使用(即将废弃)
    public function checkCouponIsUse(array $where, string $ticketCode){
        return OrderModel::query()
            ->where($where)
            ->where('status', '!=', Stakeholder::ORDER_REFUNDED)
            ->whereRaw('INSTR(coupon_info, ?) > 0', [$ticketCode])
            ->exists();
    }

    // 小程序--个人中心订单数量角标
    public function orderCountSubscript(int $mid)
    {
        // 次日达待分享
        $iterator = null;
        $orderNoArr = [];
        $group_pay_share = '0';
        $redis = $this->groupRedis;
        while (false !== ($keys = $redis->scan($iterator, "share-{$mid}*"))) {
            foreach ($keys as $key) {
                $orderNoArr = array_merge($redis->sMembers($key), $orderNoArr);
            }
        }
        if (!empty($orderNoArr)) {
            $group_pay_share = (string)OrderModel::query()->where('mid', $mid)->whereIn('order_no', $orderNoArr)->count();
        }

        $field = [
            "SUM(IF(order_source=0 and status=1, 1, 0)) as pay_off_count",
            "SUM(IF(order_source=0 and status=2 and deal_type=1, 1, 0)) as pay_delivery",
            "SUM(IF(order_source=0 and status=3 and deal_type=1, 1, 0)) as pay_received",
            "SUM(IF(order_source=0 and status=3 and deal_type=2, 1, 0)) as pay_pick",
            "SUM(IF(order_source=1 and status=1, 1, 0)) as group_pay_off_count",
            "SUM(IF(order_source=1 and (status=3 or status=2), 1, 0)) as group_pay_pick"
        ];
        $res = OrderModel::query()
            ->selectRaw(implode(',', $field))
            ->where('mid', $mid)
            ->first()->toArray();
        $res['group_pay_share'] = $group_pay_share;
        return $res;
    }

    /**
     * @param array $where
     * @param array $update
     * @return int
     */
    public function update(array $where = [], array $update = [])
    {
        return OrderModel::query()
            ->where($where)
            ->update($update);
    }





    /**
     * 分割优惠金额
     *
     * Author: mengchenchen
     * Created_at: 2021/1/3 0003 10:10
     * Updated_at: 2021/1/3 0003 14:49
     *
     * @param $total [订单总金额]
     * @param $discount [订单总折扣]
     * @param $arr [要分摊的商品列表]
     * @return array
     */
    public function splitDiscount($total, $discount, $arr)
    {
        $result = [];
        end($arr);
        $end = key($arr);
        array_walk($arr, function ($v, $k) use ($total, $discount, $end, &$result) {
            $result[$k] = round(($k == $end) ? $discount - array_sum($result) : $v['selling_price'] * $v['number'] / $total * $discount, 2);
        });
        return $result;
    }

    /**
     * 通过店铺id获取店铺当天的收入
     * @param int $shop_id
     * @param int $type
     * @return array|string
     */
    public function storesIncomes(int $shop_id,int $type)
    {
        return OrderModel::query()
            ->where(['shop_id' => $shop_id,'is_pay' => $type])
            ->selectRaw('COUNT(total_price) as count_income,SUM(total_price) as sum_income,ROUND(AVG(total_price)) as price,shop_id')
            ->whereDate('pay_at', date('Y-m-d', time()))
            ->first()
            ->toArray();
    }
    /**
     * 通过店铺id获取店铺本月的收入
     * @param int $shop_id
     * @param int $type
     * @return array|string
     */
    public function currentMonth(int $shop_id,int $type)
    {
        return OrderModel::query()
            ->where(['shop_id' => $shop_id,'is_pay' => $type])
            ->selectRaw('SUM(total_price) as month_sum,COUNT(total_price) as month_count')
            ->whereMonth('pay_at', date('m', time()))
            ->first()
            ->toArray();

    }
    /**
     * 平均价格
     * @param int $shop_id
     * @param int $type
     * @return array|string
     */
    public function avgPrice(int $shop_id,int $type)
    {
        return OrderModel::query()
            ->where([['shop_id','=',$shop_id],['is_pay','=',$type],['status','<>',5]])
            ->whereDate('pay_at', date('Y-m-d', time()))
            ->avg('total_price');
    }
    /**
     * 通过店铺id获取店铺获取流程图信息
     * @param int $shop_id
     * @param int $type
     * @return array|string
     */
    public function monthMoneySum(int $shop_id,int $type)
    {
        return OrderModel::query()
            ->where([['shop_id','=',$shop_id],['is_pay','=', $type]])
            ->selectRaw('shop_id,SUM(total_price) as month_sum_income,COUNT(total_price) as month_count_income,CONCAT(YEAR(pay_at),"-",MONTH(pay_at)) as releaseYearMonth')
            ->groupBy('releaseYearMonth')
            ->get()
            ->toArray();
    }
    /**
     * 通过店铺id获取店铺获取流程图信息
     * @param int $shop_id
     * @param int $type
     * @return array|string
     */
    public function monthMoneySums(int $shop_id,int $type)
    {
        $time = date('Y');
        $res = OrderModel::query()
            ->where([['shop_id', '=' ,$shop_id],['is_pay' ,'=', $type],['pay_at','>=', (string)$time]])
            ->selectRaw('shop_id,SUM(total_price) as month_sum_income,COUNT(total_price) as month_count_income,CONCAT(YEAR(pay_at),"-",MONTH(pay_at)) as releaseYearMonth')
            ->groupBy('releaseYearMonth')
            ->get()
            ->toArray();
        $StoreOrderRefundMonthMoney = OrderRefundService::refundAmountMonth($shop_id);
        $array = [];
        $data_count = [];
        foreach ($res as $k=>$v){
            $arr[substr($v['releaseYearMonth'], 5)] = $v['month_sum_income'] - $StoreOrderRefundMonthMoney;
            $data[substr($v['releaseYearMonth'], 5)] = $v['month_count_income'];
        }
        for($i=1; $i <=12; $i++){
            if(isset($i,$arr[$i])){
                $array[$i] = $arr[$i];
                $data_count[$i] = $data[$i];
            }else{
                $array[$i] = 0;
                $data_count[$i] = 0;
            }
        }
        $datas['price'] = $array;
        $datas['count'] = $data_count;
        return $datas;
    }



    // 获取会员已购买秒杀商品数量
    public function getPaidSecKillGoodsNum(int $mid, array $actGoodsId){
        return OrderModel::query()
            ->from('store_order as order')
            ->leftJoin('store_order_goods as og', 'order.order_no', '=', 'og.order_no')
            ->selectRaw('og.activity_goods_id,if(og.is_refund_status=0, og.number, (og.number-og.refund_number-og.shop_refund_number)) as paid_num')
            ->where(['order.mid' => $mid, 'order.is_pay' => Stakeholder::ORDER_PAID])
            ->whereIn('og.activity_goods_id', $actGoodsId)
            ->pluck('paid_num', 'activity_goods_id');
    }

    /**
     * APP小组件
     * @param int $shop_id
     * @return array
     */
    public function orderWidget(int $shop_id){
        $time = date('Y-m-d H:i:s');
        $status = [2,4,6,7,8];
        //分子
        $order_status = WidgetModel::query()->where(['store_id'=>$shop_id])->whereDate('create_time' , date('Y-m-d'))->whereIn('order_status',$status)->count();
        //分母
        $template_store = TemplateWidgetModel::query()
            ->from('t_report_goods_template_store as s')
            ->leftJoin('t_report_goods_template as r','s.template_code','=','r.template_code')
            ->where(['s.store_id'=>$shop_id])
            ->where('r.start_time','<=',$time)
            ->where('r.end_time','>=',$time)
            ->count('s.id');
        //待核销
        $notApplied=OrderModel::query()->whereRaw('status = 3 and order_type_status <> 1 and deal_type = 2')->where('shop_id', $shop_id)->count();
        //团长待分拣
        $count = TeamLeaderService::notSortingGoodsNumber($shop_id);
        //待退款
        $notRefund = OrderRefundModel::query()->where(['shop_id'=>$shop_id,'handle_type'=>1])->groupBy()->count();
        $res = [
            'notApplied' => (string)$notApplied,
            'notRefund' => (string)$notRefund,
            'order_status' => (string)$order_status,
            'template_store' => (string)$template_store,
            'notSortingNum' => (string)$count
        ];
        return $res;
    }

    /**
     * APP首页改版
     * @param int $shop_id
     * @return array
     */
    public function homeIndex(int $shop_id){
        //提示语
        $shopNameArr = $this->shopService->getInfoByShopId($shop_id);
        $shopName = $shopNameArr['shop_name'];
        $time = date('H');
        if (5 <= (int)$time && (int)$time < 7){
            $prompt = '清晨打卡,'.$shopName;
        }elseif(7 <= (int)$time && (int)$time < 9){
            $prompt = '早上好,'.$shopName;
        }elseif (9 <= (int)$time && (int)$time < 12){
            $prompt = '上午好,'.$shopName;
        }elseif (12 <= (int)$time && (int)$time < 14){
            $prompt = '中午好,'.$shopName;
        }elseif (14 <= (int)$time && (int)$time < 18){
            $prompt = '下午好,'.$shopName;
        }elseif (18 <= (int)$time && (int)$time < 19){
            $prompt = '傍晚好,'.$shopName;
        }elseif (19 <= (int)$time && (int)$time < 24){
            $prompt = '晚上辛苦了,'.$shopName;
        }elseif (24 == (int)$time){
            $prompt = '凌晨打卡,'.$shopName;
        }elseif (0 <= (int)$time && (int)$time < 5){
            $prompt = '凌晨打卡,'.$shopName;
        }
        //销售金额
        $amoutData = self::storesIncomes($shop_id,self::ORDER_IS_PAY_1);
        if(empty($amoutData['sum_income'])){
            $salesAmount = "0";
        }else{
            $salesAmount = $amoutData['sum_income'];
        }
        //上周今天销售金额
        $amount = OrderModel::query()
            ->where(['shop_id' => $shop_id,'is_pay' => 1])
            ->selectRaw('SUM(total_price) as sum_income,shop_id')
            ->whereDate('pay_at' , date('Y-m-d',strtotime('-1 week')))
            ->first()
            ->toArray();
        if(empty($amount['sum_income'])){
            $listAmount = "0";
        }else{
            $listAmount = $amount['sum_income'];
        }
        //差集
        $difference = $salesAmount - $listAmount;
        if ($difference<0){
            $diff = - $difference;
        }else{
            $diff = $difference;
        }
        //百分比
        if($listAmount == 0){
            $pct = 0;
        }else{
            $pct = round(($diff/$listAmount)*100);
        }
        if ($difference<0 && $listAmount != 0){
            $pct = - $pct;
        }
        $res = self::orderWidget($shop_id);
        //待核销订单总金额
        $notApplied=OrderModel::query()->whereRaw('status = 3 and order_type_status <> 1 and deal_type = 2')->where('shop_id', $shop_id)->selectRaw('SUM(total_price) as sum_income')->first()->toArray();
        //待退款订单总金额
        $notRefund = OrderRefundModel::query()->where(['shop_id'=>$shop_id,'handle_type'=>1])->selectRaw('SUM(refund_money) as money')->first()->toArray();
        //门店下所有团长的分拣商品总数
        $num = TeamLeaderService::sortingGoodsNumber($shop_id);
        //门店下所有团长的已分拣数量
        $sortingNum = TeamLeaderService::endSortingGoodsNumber($shop_id);
        //待分拣数量
        $notSortingNum = (int)$num - (int)$sortingNum;
        //待提交报货单
        $invoice = $res['order_status'] - $res['template_store'];
        if($invoice <0){
            $invoice = - $invoice;
        }
        // 当前时间的前24小时
        $start = date('YmdH', strtotime('-23 hours'));
        $end = date('YmdH');
        $ftime = date('Y-m-d H:i:s',strtotime('-23 hours'));
        $dateTime = date('Y-m-d H:i:s');
        $times = $this->baseService::prTime($ftime,$dateTime);
        $timeRes = [];
        foreach ($times as $v){
            $timeRes[]['time'] = $v;
        }
        $arr = OrderModel::query()
            ->where(['shop_id'=>$shop_id,'is_pay'=> 1])
            ->whereRaw("DATE_FORMAT(pay_at,'%Y%m%d%H') > $start and DATE_FORMAT(pay_at,'%Y%m%d%H') <= $end")
            ->select([
                'shop_id',
                Db::raw('COUNT(1) as order_number'),
                Db::raw('SUM(total_price) as total_price'),
                Db::raw('GROUP_CONCAT(order_no) as order_nos'),
                Db::raw("DATE_FORMAT(pay_at,'%Y-%m-%d %H') as time")
            ])
            ->groupBy(['time'])
            ->get()
            ->toArray();
        $arrData = array_column($arr,null,'time');
        //排行TOP3
        $order_no =OrderModel::query()
            ->from('store_order_goods as g')
            ->join('store_order as s','s.order_no','=', 'g.order_no')
            ->where(['s.shop_id'=>$shop_id,'s.is_pay'=> 1])
            ->whereRaw("DATE_FORMAT(s.pay_at,'%Y%m%d%H') > $start and DATE_FORMAT(s.pay_at,'%Y%m%d%H') <= $end")
            ->select([
                'g.goods_id',
                'g.goods_title',
                Db::raw('SUM(g.selling_price) as selling_price'),
                Db::raw("DATE_FORMAT(s.pay_at,'%Y-%m-%d %H') as time"),
            ])
            ->groupBy(['time'],['g.goods_id'])
            ->get()
            ->toArray();
        $order = [];
        foreach ($order_no as $v){
            $order[$v['time']][] = $v;
        }
        $orderData = [];
        foreach ($order as $m=>$s){
            // 小于等于3个
            usort($s, function ($a, $b) {
                if ($a['selling_price'] == $b['selling_price']) {
                    return 0;
                }
                return ($a['selling_price'] < $b['selling_price']) ? 1: -1 ;
            });
            if(count($s)  <= 3){
                $orderData[$m] = $s;
                continue;
            }
            $orderData[$m] = array_slice($s,0,3);
        }
        foreach ($timeRes as $k => &$v){
            if (isset($arrData[$v['time']])) {
                $v['order_number'] = $arrData[$v['time']]['order_number'];
                $v['total_price'] = (string)$arrData[$v['time']]['total_price'];
            }else{
                $v['order_number'] = 0;
                $v['total_price'] = "0";
            }
        }
        foreach ($timeRes as $i => &$e){
            if (isset($orderData[$e['time']])) {
                $e['top'] = $orderData[$e['time']];
            }else{
                $e['top'] = [];
            }
        }
        $data = [
            'prompt' => $prompt,
            'amoutData' => $salesAmount,
            'amount' => $listAmount,
            'pct' => $pct,
            'notApplied' => $res['notApplied']?? "0",
            'notApplied_money' => $notApplied['sum_income']?? "0",
            'notRefund' => $res['notRefund']?? "0",
            'notRefund_money' => $notRefund['money']?? "0",
            'order_status' => $res['order_status']?? "0",
            'template_store' => $res['template_store']?? "0",
            'invoice' => $invoice ?? 0,
            'notSorting' => $res['notSortingNum']?? "0",
            'notSortingNum' => $notSortingNum ??0,
            'list' => $timeRes
        ];
            return $data;
    }


    /**
     * 获取店铺营业状态
     * @return bool
     */
    public function getSystemStatus()
    {
       $status = SystemModel::where(['name'=>'system_status'])->value('value');
       if($status && $status !=1){
           return false;
       }
       return true;
    }
}
